#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@file modbus_driver.py
@brief Modbus RTU驱动层
@details 提供底层Modbus RTU通信接口，与硬件直接交互
@author Motor Controller Team
@date 2024
"""

import logging
import time
from typing import Optional, List
from pymodbus.client import ModbusSerialClient
from pymodbus.exceptions import ModbusException

from core.logging_config import get_logger

logger = get_logger(__name__)


class ModbusDriver:
    """
    @brief Modbus RTU驱动类
    @details 负责与电机驱动器的底层Modbus RTU通信
    """
    
    def __init__(self, port: str, baudrate: int, device_id: int, 
                 timeout: float = 1.0, bytesize: int = 8, 
                 parity: str = 'N', stopbits: int = 1):
        """
        @brief 初始化Modbus驱动
        @param port 串口端口
        @param baudrate 波特率
        @param device_id 设备ID
        @param timeout 超时时间
        @param bytesize 数据位
        @param parity 校验位
        @param stopbits 停止位
        """
        self.port = port
        self.baudrate = baudrate
        self.device_id = device_id
        self.timeout = timeout
        self.bytesize = bytesize
        self.parity = parity
        self.stopbits = stopbits
        
        self.client: Optional[ModbusSerialClient] = None
        self.connected = False
        
        logger.info(f"Modbus驱动初始化 - 端口: {port}, 波特率: {baudrate}, 设备ID: {device_id}")
    
    def connect(self) -> bool:
        """
        @brief 连接到设备
        @return bool 连接是否成功
        @retval True 连接成功
        @retval False 连接失败
        """
        try:
            self.client = ModbusSerialClient(
                port=self.port,
                baudrate=self.baudrate,
                bytesize=self.bytesize,
                parity=self.parity,
                stopbits=self.stopbits,
                timeout=self.timeout
            )
            
            if self.client.connect():
                self.connected = True
                logger.info(f"Modbus连接成功 - 端口: {self.port}")
                return True
            else:
                logger.error(f"Modbus连接失败 - 端口: {self.port}")
                return False
                
        except Exception as e:
            logger.error(f"Modbus连接异常: {e}")
            return False
    
    def disconnect(self) -> None:
        """
        @brief 断开连接
        """
        if self.client and self.connected:
            self.client.close()
            self.connected = False
            logger.info("Modbus连接已断开")
    
    def is_connected(self) -> bool:
        """
        @brief 检查连接状态
        @return bool 是否已连接
        """
        return self.connected and self.client is not None
    
    def write_register(self, address: int, value: int) -> bool:
        """
        @brief 写入单个寄存器
        @param address 寄存器地址
        @param value 要写入的值
        @return bool 写入是否成功
        """
        if not self.is_connected():
            logger.error("Modbus未连接")
            return False
            
        try:
            result = self.client.write_register(address, value, device_id=self.device_id)
            if result.isError():
                logger.error(f"写入寄存器失败 - 地址: 0x{address:02X}, 值: {value}")
                return False
            else:
                logger.debug(f"写入寄存器成功 - 地址: 0x{address:02X}, 值: {value}")
                return True
                
        except ModbusException as e:
            logger.error(f"Modbus写入异常: {e}")
            return False
        except Exception as e:
            logger.error(f"写入寄存器异常: {e}")
            return False
    
    def write_registers(self, address: int, values: List[int]) -> bool:
        """
        @brief 写入多个寄存器
        @param address 起始寄存器地址
        @param values 要写入的值列表
        @return bool 写入是否成功
        """
        if not self.is_connected():
            logger.error("Modbus未连接")
            return False
            
        try:
            result = self.client.write_registers(address, values, device_id=self.device_id)
            if result.isError():
                logger.error(f"写入寄存器失败 - 地址: 0x{address:02X}, 值: {values}")
                return False
            else:
                logger.debug(f"写入寄存器成功 - 地址: 0x{address:02X}, 值: {values}")
                return True
                
        except ModbusException as e:
            logger.error(f"Modbus写入异常: {e}")
            return False
        except Exception as e:
            logger.error(f"写入寄存器异常: {e}")
            return False
    
    def read_register(self, address: int) -> Optional[int]:
        """
        @brief 读取单个寄存器
        @param address 寄存器地址
        @return Optional[int] 寄存器值
        """
        if not self.is_connected():
            logger.error("Modbus未连接")
            return None
            
        try:
            result = self.client.read_holding_registers(address, count=1, device_id=self.device_id)
            if result.isError():
                logger.error(f"读取寄存器失败 - 地址: 0x{address:02X}")
                return None
            else:
                value = result.registers[0]
                logger.debug(f"读取寄存器成功 - 地址: 0x{address:02X}, 值: {value}")
                return value
                
        except ModbusException as e:
            logger.error(f"Modbus读取异常: {e}")
            return None
        except Exception as e:
            logger.error(f"读取寄存器异常: {e}")
            return None
    
    def read_registers(self, address: int, count: int) -> Optional[List[int]]:
        """
        @brief 读取多个寄存器
        @param address 起始寄存器地址
        @param count 要读取的寄存器数量
        @return Optional[List[int]] 寄存器值列表
        """
        if not self.is_connected():
            logger.error("Modbus未连接")
            return None
            
        try:
            result = self.client.read_holding_registers(address, count=count, device_id=self.device_id)
            if result.isError():
                logger.error(f"读取寄存器失败 - 地址: 0x{address:02X}, 数量: {count}")
                return None
            else:
                values = result.registers
                logger.debug(f"读取寄存器成功 - 地址: 0x{address:02X}, 数量: {count}, 值: {values}")
                return values
                
        except ModbusException as e:
            logger.error(f"Modbus读取异常: {e}")
            return None
        except Exception as e:
            logger.error(f"读取寄存器异常: {e}")
            return None
    
    def test_communication(self) -> bool:
        """
        @brief 测试通信
        @return bool 通信是否正常
        """
        if not self.is_connected():
            return False
        
        try:
            # 尝试读取一个寄存器来测试通信
            result = self.read_register(0x00)
            return result is not None
        except Exception as e:
            logger.error(f"通信测试异常: {e}")
            return False
    
    def send_command(self, command: str) -> str:
        """
        @brief 发送串口命令
        @param command 要发送的命令
        @return str 发送结果
        """
        try:
            if not self.is_connected():
                return "错误: 串口未连接"
            
            # 使用ModbusSerialClient的正确方法发送数据
            if hasattr(self.client, 'socket'):
                # 如果有socket对象，直接发送
                serial_port = self.client.socket
                if serial_port:
                    # 将命令转换为字节并发送
                    command_bytes = command.encode('utf-8')
                    serial_port.write(command_bytes)
                    
                    # 等待响应
                    time.sleep(0.1)
                    
                    # 读取响应
                    try:
                        if hasattr(serial_port, 'in_waiting') and serial_port.in_waiting > 0:
                            response = serial_port.read(serial_port.in_waiting)
                            if response:
                                return response.decode('utf-8', errors='ignore')
                    except Exception as read_error:
                        logger.warning(f"读取响应时出错: {read_error}")
                    
                    return "无响应"
                else:
                    return "错误: 串口对象不可用"
            else:
                return "错误: 串口对象不存在"
                
        except Exception as e:
            logger.error(f"发送串口命令异常: {e}")
            return f"错误: {e}"
    
    def receive_data(self) -> str:
        """
        @brief 接收串口数据
        @return str 接收到的数据
        """
        try:
            if not self.is_connected():
                return "错误: 串口未连接"
            
            # 使用ModbusSerialClient的正确方法读取数据
            # 尝试读取串口缓冲区中的数据
            if hasattr(self.client, 'socket'):
                # 如果有socket对象，直接读取
                serial_port = self.client.socket
                if serial_port:
                    # 检查是否有数据可读
                    if hasattr(serial_port, 'in_waiting') and serial_port.in_waiting > 0:
                        data = serial_port.read(serial_port.in_waiting)
                        if data:
                            # 解码数据并清理
                            decoded_data = data.decode('utf-8', errors='ignore').strip()
                            if decoded_data:
                                return decoded_data
                    else:
                        # 尝试读取少量数据
                        try:
                            data = serial_port.read(1)  # 读取1个字节
                            if data:
                                # 继续读取更多数据
                                time.sleep(0.01)  # 短暂等待
                                if hasattr(serial_port, 'in_waiting') and serial_port.in_waiting > 0:
                                    more_data = serial_port.read(serial_port.in_waiting)
                                    data += more_data
                                
                                # 解码数据
                                decoded_data = data.decode('utf-8', errors='ignore').strip()
                                if decoded_data:
                                    return decoded_data
                        except:
                            pass
            else:
                # 如果没有socket对象，返回空
                return ""
                
            return ""
                
        except Exception as e:
            logger.error(f"接收串口数据异常: {e}")
            return f"错误: {e}"
